/**
 * Licensed under the Apache License Version 2.0.
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package net.interknit.knitter.cg.template;

import java.util.Hashtable;
import java.util.Map;

import net.interknit.knitter.cg.layout.LayoutElement;
import net.interknit.knitter.cg.util.ReflectionHelper;

/**
 *
 */
public abstract class Template
{
	private Map<String, String> placeholderReplacements;

	/**
	 * Get the package name for the JavaType, or an empty String if the JavaType does not have a package
	 * (package-less class)
	 *
	 * @return Name of the JavaType package or an empty String for package-less classes
	 */
	public abstract String getJavaPackageName();

	/**
	 * Get the unqualified name of the Java Class for this JavaType
	 *
	 * @return Unqualified name of the JavaClass for this JavaType
	 */
	public abstract String getJavaClassName();

	public abstract String[] getPlaceholders();

	public abstract LayoutElement getLayoutElement();

	/**
	 * Should source generation for this Template be ignored?
	 *
	 * @return if true, source generation will be ignored.  If false, source generation will take place.
	 */
	public boolean skipSourceGeneration()
	{
		return false;
	}

	/**
	 * Get the derived name of the template
	 *
	 * @return Name of the template
	 */
	public String getTemplateName()
	{
		return ReflectionHelper.getClassName(this.getClass(), true);
	}

	/**
	 * Build me
	 *
	 * @return Built me
	 */
	public Template build()
	{
		if(placeholderReplacements == null)
		{
			placeholderReplacements = new Hashtable<String, String>();
			for(String placeholder : getPlaceholders())
			{
				try
				{
					String value = String.valueOf(
							this.getClass().getMethod(placeholder).invoke(
									this));

					placeholderReplacements.put(placeholder, value);
				}
				catch(Exception e)
				{
					throw new RuntimeException(e);
				}
			}
		}

		return this;
	}

	public String value(String placeholder)
	{
		String replacement = null;
		if(placeholderReplacements != null)
			replacement = placeholderReplacements.get(placeholder);

		if(replacement != null)
		{
			return "null".equals(replacement) ? null : replacement;
		}
		else
		{
			throw new RuntimeException(
					this.getClass().getName() + " does not have value for placeholder " +
					placeholder + ". " + "Check whether this class has a public method called " +
					placeholder + ", and that build() was called before value() was called.");
		}
	}
}
